/**
 * 封装空气质量图表
 * author  aty
 * 
 * 调用说明
 * new Aqi({
 * 	 el:"css选择器",
 *	 maxValue:[100,50,1,80,100,100],		此参数不传就从value中获取最大的值
 *	 background:"#000",
 *	 color:['red','blue','green','pink','orange','yellow'],
 *	 barWidth:6,
 *	 showTitle:true,
 *	 orient:"horizontal",
 *	 value:[
 *		{name:"颗粒物",unit:"(mg/m³)",value:200},
 *		{name:"PM2.5",unit:"(mg/m³)",value:0.512},
 *		{name:"PM10",unit:"(mg/m³)",value:0.085},
 *		{name:"温度",unit:"°C",value:28.5},
 *		{name:"湿度",unit:"%",value:200},
 *		{name:"大气压",unit:"kpa",value:45.98}
 *	 ]
 *})
 */


function Aqi(options){
	if(!options.el){
		throw new Error("error: el挂载参数必须存在");return;
	}
	this.options = {
		orient:"horizontal",
		showTitle:true,
		barWidth:6,
		color:[],
	}
	$.extend(this.options,options);

	// 如果没有传入maxValue参数
	if(!this.options.hasOwnProperty("maxValue")){
		this.getMaxNumberByValue();
		this.hasFixedMaxValue = false;
	}else{
		this.hasFixedMaxValue = true;
	}

	this.init();
}

Aqi.prototype.init = function(){
	this.initStyle();
}

Aqi.prototype.getMaxNumberByValue = function(){
	var self = this;
	var curValue = 0;
	var len = this.options.value.length;

	this.options.value.forEach(function(ele){
		curValue = Number(ele.value)>curValue?Number(ele.value):curValue;
	});

	var newArr = [];
	for(var i = 0;i < len; i++ ){
		newArr.push(curValue);
	}
	this.options.maxValue = newArr;
}


Aqi.prototype.initStyle = function(){
	var self = this;
	var container = $(this.options.el);
		container.addClass("aqi-plus");
		this.initData(container)


	// 修改数据
	this.setValue = function(options){
		$.extend(self.options,options);
		// 没有固定的最大值
		if(!self.hasFixedMaxValue){
			self.getMaxNumberByValue();
		}
		self.initData(container)
	}
}

Aqi.prototype.initData = function(container){
	var self = this;
	var ul = document.createElement("ul");
		ul.style.height = container.height() + "px";
		ul.className = "aqi-ul " + (this.options.orient=="horizontal"?"aqi-horizontal":"aqi-vertical");
	this.options.value.forEach(function(row,i){
		var li = document.createElement("li");
		li.className = "aqi-li";
		if(self.options.orient=="horizontal"){
			li.style.height = Math.floor(self.divide(Math.floor(container.height()),self.options.value.length)) + "px"; 
			if(self.options.showTitle){
				var pTitle = document.createElement("p");
					pTitle.className = "aqi-header flex mgb-6";
					pTitle.style.minHeight = "20px";
				var name = document.createElement("span");
					name.className = "type-name grow";
					name.innerHTML = row.name || "";
				var valueBox = document.createElement("div");
					valueBox.className = "type-value-box";
				var value = document.createElement("span");
					value.className = "type-value";
					value.innerHTML = row.value || "";
				var unit = document.createElement("span");
					unit.className = "type-util";
					unit.innerHTML = row.unit || "";
					valueBox.appendChild(value);	
					valueBox.appendChild(unit);	
					pTitle.appendChild(name);
					pTitle.appendChild(valueBox);
					li.appendChild(pTitle);
			}
			var pRate = document.createElement("p");
			pRate.className = "aqi-rate";
			pRate.style.minHeight = self.options.barWidth+"px" || "10px";
			pRate.style.background = self.options.background || "rgba(180, 180, 181, 0.2)";

			var rate = document.createElement("span");
				rate.className = "rate-item";
				rate.style.background = self.options.color[i] || "rgba(0,0,0,0.5)";
				pRate.appendChild(rate);

				setTimeout(()=>{
					rate.style.width = self.divide(Number(row.value),Number(self.options.maxValue[i])).toFixed(2)*100 + "%";
				},20)
			li.appendChild(pRate);
		}else{
			li.style.height = container.height() + "px"; 
			li.style.width = Math.floor(self.divide(Math.floor(container.width()),self.options.value.length)) + "px";

			var valueBox = document.createElement("div");
				valueBox.className = "v-type-value-box";
			var value = document.createElement("span");
				value.className = "v-type-value";
				value.innerHTML = row.value || "";
			var unit = document.createElement("span");
				unit.className = "v-type-util";
				unit.innerHTML = row.unit || "";
				valueBox.appendChild(value);	
				valueBox.appendChild(unit);	
				li.appendChild(valueBox)


			var pRate = document.createElement("div");
				pRate.className = "v-p-rate";
				pRate.style.background = self.options.background || "rgba(180, 180, 181, 0.2)";
			var rate = document.createElement("div");
				rate.className = "v-rate";
				rate.style.background = self.options.color[i] || "rgba(0,0,0,0.5)";
				pRate.appendChild(rate)
				li.appendChild(pRate)

			var name = document.createElement("div");	
				name.className = "v-name";
				name.innerHTML = row.name || "";
				li.appendChild(name)

				setTimeout(()=>{
					rate.style.height = self.divide(Number(row.value),Number(self.options.maxValue[i])).toFixed(2)*100 + "%";
				},20)

		}
		ul.appendChild(li);
	})
	container.html(ul);

	// 如果是水平排列并且是隐藏title信息的就渲染右侧legend
	if(self.options.orient=="horizontal" && !self.options.showTitle){
		var legend = document.createElement("div");
			legend.className = "legend-box";
		var dl = document.createElement("dl");

		this.options.value.forEach(function(item,idx){
			var dd = document.createElement("dd");
			var i = document.createElement("i");
				i.style.background = self.options.color[idx];
			var dlName = document.createElement("span");
				dlName.className = "name";
				dlName.innerHTML = item.name;
			var dlValue = document.createElement("span");
				dlValue.innerHTML = item.value;

			dd.appendChild(i);
			dd.appendChild(dlName);
			dd.appendChild(dlValue);
			dl.appendChild(dd);

			dd.onmouseenter = function(){
				$(ul).find("li").removeClass("hover").eq(idx).addClass("hover");
			}

		});

		dl.onmouseout = function(){
			$(ul).find("li").removeClass("hover");
		}

		legend.appendChild(dl);
		container.addClass("flex");
		ul.classList.add("grow");
		container.append(legend);
	}

}

/*
 * 核心方法，实现加减乘除运算，确保不丢失精度
 * 思路：把小数放大为整数（乘），进行算术运算，再缩小为小数（除）
 *
 * @param a {number} 运算数1
 * @param b {number} 运算数2
 * @param op {string} 运算类型，有加减乘除（add/subtract/multiply/divide）
 *
 */
Aqi.prototype.operation = function(a, b, op){
	var o1 = this.toInteger(a);
    var o2 = this.toInteger(b);
    var n1 = o1.num;
    var n2 = o2.num;
    var t1 = o1.times;
    var t2 = o2.times;
    var max = t1 > t2 ? t1 : t2;
    var result = null;
    switch (op) {
        case 'add':
            if (t1 === t2) { // 两个小数位数相同
                result = n1 + n2
            } else if (t1 > t2) { // o1 小数位 大于 o2
                result = n1 + n2 * (t1 / t2)
            } else { // o1 小数位 小于 o2
                result = n1 * (t2 / t1) + n2
            }
            return result / max;
        case 'subtract':
            if (t1 === t2) {
                result = n1 - n2
            } else if (t1 > t2) {
                result = n1 - n2 * (t1 / t2)
            } else {
                result = n1 * (t2 / t1) - n2
            }
            return result / max;
        case 'multiply':
            result = (n1 * n2) / (t1 * t2);
            return result;
        case 'divide':
            result = (n1 / n2) * (t2 / t1);
            return result
    }
}

// 加
Aqi.prototype.add = function(a, b){
	return this.operation(a, b, 'add')
}

// 减
Aqi.prototype.subtract = function(a, b){
	return this.operation(a, b, 'subtract')
}

// 乘
Aqi.prototype.multiply = function(a, b){
	return this.operation(a, b, 'multiply')
}

// 除
Aqi.prototype.divide = function(a, b){
	return this.operation(a, b, 'divide')
}


// 判断obj是否为一个整数
Aqi.prototype.isInteger = function(obj){
	 return Math.floor(obj) === obj
}

/*
 * 将一个浮点数转成整数，返回整数和倍数。如 3.14 >> 314，倍数是 100
 * @param floatNum {number} 小数
 * @return {object}
 *   {times:100, num: 314}
 */
Aqi.prototype.toInteger = function(floatNum){
	var ret = {times: 1, num: 0};
    if (this.isInteger(floatNum)) {
        ret.num = floatNum;
        return ret
    }
    var strfi = floatNum + '';
    var dotPos = strfi.indexOf('.');
    var len = strfi.substr(dotPos + 1).length;
    var times = Math.pow(10, len);
    var intNum = parseInt(floatNum * times + 0.5, 10);
    ret.times = times;
    ret.num = intNum;
    return ret
}


